package com.lw.smartdevice.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.lw.smartdevice.dto.UserDto;
import com.lw.smartdevice.enums.CheckType;
import com.lw.smartdevice.enums.LoginResultEnum;
import com.lw.smartdevice.events.MyLoginEvent;
import com.lw.smartdevice.exceptions.AddMyBaseException;
import com.lw.smartdevice.exceptions.MyBaseException;
import com.lw.smartdevice.exceptions.MyErrorCode;
import com.lw.smartdevice.mapper.SysUserInfoMapper;
import com.lw.smartdevice.pojo.SysUserInfo;
import com.lw.smartdevice.service.SysUserInfoService;
import com.lw.smartdevice.utils.MD5Utils;
import com.lw.smartdevice.utils.MyStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.List;

/**
 * @author Administrator
 * @version 1.0
 * @description:
 * @date 2022/3/14 17:27
 */
@Service
@Transactional
public class SysUserServiceImpl implements SysUserInfoService {

    private ApplicationContext applicationContext;

    @Autowired
    public void setApplicationContext(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    private Logger logger = LoggerFactory.getLogger(SysUserServiceImpl.class);

    private SysUserInfoMapper sysUserInfoMapper;

    @Autowired
    public void setSysUserInfoMapper(SysUserInfoMapper sysUserInfoMapper) {
        this.sysUserInfoMapper = sysUserInfoMapper;
    }

    @Override
    public SysUserInfo login(UserDto userDto) {
        //登录
        //校验，用户传递的账号和密码不为空
        Assert.isTrue(StringUtils.hasText(userDto.getUsername())&&StringUtils.hasText(userDto.getPassword()),()->{
            throw new MyBaseException("用户名密码不能为空",MyErrorCode.DATA_NULL);
        });
        //根据用户名查询
        SysUserInfo userInfo = sysUserInfoMapper.findByUsername(userDto.getUsername());
        //查询到了就获取盐
        Assert.notNull(userInfo,()->{
            throw new MyBaseException("用户名或密码错误",MyErrorCode.USERNAME_PASSWORD_ERROR);
        });

        String pwdSalt = userInfo.getPwdSalt();
        //用盐将传递过来的密码转成散列值
        //按照之前注册的时候的规则计算散列值
        String pwdMD5 = MD5Utils.getMd5(userDto.getPassword(), pwdSalt, 1024);
        //和刚查询的密码进行比较
        Assert.isTrue(pwdMD5.equalsIgnoreCase(userInfo.getPassword()),()->{
            //记录日志
            applicationContext.publishEvent(new MyLoginEvent(LoginResultEnum.FAIL,userDto.getUsername()));
            throw new MyBaseException("用户名或密码错误",MyErrorCode.USERNAME_PASSWORD_ERROR);
        });

        userInfo.setPassword(null);//防止将密码泄露到前端
        userInfo.setPwdSalt(null);//防止将盐泄露到前端
        //记录日志
        applicationContext.publishEvent(new MyLoginEvent(LoginResultEnum.SUCCESS ,userDto.getUsername()));
        return userInfo;
    }

    @Override
    public SysUserInfo findById(Long userId) {
        return sysUserInfoMapper.findById(userId);
    }

    @Override
    public PageInfo<SysUserInfo> findAll(int pageNum,int pageSize) {
        PageHelper.startPage(pageNum,pageSize);
        List<SysUserInfo> sysUserInfoList = sysUserInfoMapper.findAll();
        PageInfo<SysUserInfo> pageInfo = new PageInfo<>(sysUserInfoList);
        return pageInfo;
    }

    @Override
    public void addUser(SysUserInfo sysUserInfo) {
        //校验
        //传入数据是否为空
        Assert.isTrue(!sysUserInfo.isEmpty(CheckType.ADD),()->{
            throw new MyBaseException("数据为空", MyErrorCode.DATA_NULL);
        });

        //校验手机号、邮箱是否符合规范
        //校验手机号
        Assert.isTrue(MyStringUtils.check(sysUserInfo.getPhone(),MyStringUtils.mobileRegex),()->{
            throw new AddMyBaseException("手机号不合法",MyErrorCode.PHONE_REG_NOT_MACTH);
        });

        //校验邮箱
        Assert.isTrue(MyStringUtils.check(sysUserInfo.getEmail(),MyStringUtils.emailRegex),()->{
            throw new AddMyBaseException("邮箱不符合规范",MyErrorCode.MAIL_REG_NOT_MACTH);
        });

        //校验唯一数据
        //用户名、手机号和邮箱必须检查
        //检查用户名
        SysUserInfo username = sysUserInfoMapper.findByUsername(sysUserInfo.getUsername());
        Assert.isNull(username,()->{
            throw new AddMyBaseException("用户名已存在",MyErrorCode.USER_ALREADY_EXIST);
        });

        //检查手机号
        SysUserInfo phone = sysUserInfoMapper.findByPhone(sysUserInfo.getPhone());
        Assert.isNull(phone,()->{
            throw new AddMyBaseException("手机号已存在",MyErrorCode.PHONE_ALREADY_EXIST);
        });

        //检查邮箱
        SysUserInfo email = sysUserInfoMapper.findByEmail(sysUserInfo.getEmail());
        Assert.isNull(email,()->{
            throw new AddMyBaseException("邮箱已存在",MyErrorCode.EMAIL_ALREADY_EXIST);
        });

        //生成盐
        String randomString = MD5Utils.getRandomString(10);
        sysUserInfo.setPwdSalt(randomString);
        //生成密码
        String md5 = MD5Utils.getMd5(sysUserInfo.getPassword(), randomString, 1024);//计算密码的MD5值
        sysUserInfo.setPassword(md5);//将密码设置为MD5值

        //设置默认数据
        sysUserInfo.setCreateTime(new Date());
        //检查当前登录的用户,如果是管理员,设置管理员的信息,如果没有用户就是用户自己注册的
        sysUserInfo.setCreateBy(sysUserInfo.getUsername());
        sysUserInfo.setRemark("普通用户");
        //保存到数据库
        sysUserInfoMapper.addUser(sysUserInfo);
        logger.error("添加成功");
    }
}
